//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
/*
   Interrupt hander for the system timer and CS8900a interrupt
*/
#include "config.h"
#include "bulverde.h"
#include "time.h"
#include "serial.h"
#include "smc91x.h"

void sti(void)
{
    asm volatile("stmfd sp!, {r0}");
    asm volatile("mrs r0, cpsr");
    asm volatile("bic r0, r0, #0x80");
    asm volatile("msr cpsr, r0");
    asm volatile("ldmfd sp!, {r0}");
}

void cli(void)
{
    asm volatile("stmfd sp!, {r0}");
    asm volatile("mrs r0, cpsr");
    asm volatile("orr r0, r0, #0x80");
    asm volatile("msr cpsr, r0");
    asm volatile("ldmfd sp!, {r0}");
}

extern void pcf50606_interrupt_entry (void);
void check_onkey();
void c_irq(void)
{

    int interrupt_status;
    cli();
    interrupt_status = (__REG(INTC_BASE_PHYSICAL+ICIP_OFFSET) & __REG(INTC_BASE_PHYSICAL+ICMR_OFFSET)); /* check onlu un-masked interrupts */
//  HEX_LED(interrupt_status);

    if ((interrupt_status & IRQ_OST0) != 0) { /* timer interrupt */

        jiffies++;
        check_onkey();
        __REG(OST_BASE_PHYSICAL+OSMR0_OFFSET) = __REG(OST_BASE_PHYSICAL+OSCR0_OFFSET) + (3250000L)/TIMER_TICK_PER_SEC ; /* Trigger interrupts every 10 ms */
        __REG(OST_BASE_PHYSICAL+OSSR_OFFSET) = OSSR_M0; /* clear the inerrupt */

        /* this timer does not count the time required to handle the interrupt,
         * so actually jiffies take a little longer than 10ms.
         */
//  return;
// } else if((interrupt_status & IRQ_GPIO0) != 0) { // FPGA interrupt, We use as a Ethernet IRQ only
//  net_interrupt(&net_dev_lan91c111);

        /* We should some work for clearing FPGA interrupt status bit */
//  __REG(GPIO_BASE_PHYSICAL+GEDR0_OFFSET) = IRQ_GPIO0;
// } else { /* unknown sources, neglect */
    }

    if ((interrupt_status & IRQ_GPIO0) != 0) {
        pcf50606_interrupt_entry();
    }

#if 0
    if ((interrupt_status & IRQ_OST_4_11) != 0) {

//  if( *(unsigned int *)(GPIO_BASE_PHYSICAL + GPLR3_OFFSET) & 0x00800000 )
//   *(unsigned int *)(GPIO_BASE_PHYSICAL + GPCR3_OFFSET) = 0x01000000;
//  else
//   *(unsigned int *)(GPIO_BASE_PHYSICAL + GPSR3_OFFSET) = 0x01000000;

        if (__REG(OST_BASE_PHYSICAL + OSSR_OFFSET) & OSSR_M4) {

            jiffies_div10++;

//   __REG(OST_BASE_PHYSICAL+OSCR4_OFFSET) = 0; /* reset the counter */
            __REG(OST_BASE_PHYSICAL+OSSR_OFFSET) = OSSR_M4; /* clear the inerrupt */
        }
    }
#endif

    sti();
}
